package de.rtbfaustball.converters;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import org.apache.pdfbox.exceptions.COSVisitorException;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.edit.PDPageContentStream;
import org.apache.pdfbox.pdmodel.font.PDType1Font;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import de.rtbfaustball.model.clubs.Club;
import de.rtbfaustball.model.clubs.ClubContact;
import de.rtbfaustball.model.clubs.ClubVenue;
import de.rtbfaustball.sort.ListSorter;

/**
 * Convert club information from xml files to wordpress-ready html, to pdf and to excel. Is able to persist the results as well.
 * 
 * @see src/main/resources/data/clubs
 * @author sebastian
 */
public class ClubInformationConverter extends AbstractConverter {

	private static final String RESOURCE_PATH = "src\\main\\resources\\data\\clubs";
	private static final String VENUE_TYPE_INDOOR = "indoor";
	private static final String VENUE_TYPE_OUTDOOR = "outdoor";

	private Logger log = LoggerFactory.getLogger(ClubInformationConverter.class);

	/** List containing all clubs from "src/main/resources/data/clubs". Filled in constructor. */
	private List<Club> clubs;

	/**
	 * Constructs object and reads club information from xml files.
	 * 
	 * @throws JAXBException
	 */
	public ClubInformationConverter() throws JAXBException {
		JAXBContext context = JAXBContext.newInstance(new Class[] { Club.class });
		Unmarshaller unmarshaller = context.createUnmarshaller();

		clubs = new ArrayList<Club>();
		File folder = new File(RESOURCE_PATH);

		for (File file : folder.listFiles()) {
			if (file.getName().endsWith(".xml")) {
				clubs.add((Club)unmarshaller.unmarshal(file));
			}
		}

		ListSorter.sort(clubs);
	}

	// *************** Conversion routines *************************************

	/**
	 * {@inheritDoc}
	 */
	@Override
	public void toHtml(boolean persist) throws IOException {
		log.info("Start clubs conversion to HTML");

		StringBuffer markup = new StringBuffer();
		markup.append("<style>");
		markup.append("ul.floated-content { list-style: none; padding: 0; margin: 0; }");
		markup.append("ul.floated-content li { float: left; width: 50%; padding-top: 0px; min-width: 199px; }");
		markup.append("ul.floated-content p.caption { margin-bottom: 0; }");
		markup.append("ul.floated-content p strong { border-bottom: solid 1px #ddd; }");
		markup.append("</style>");

		markup.append("Alle Kontaktdaten der Faustballvereine im Rheinischen Turnerbund inklusive Adressen der Sportplätze und -hallen auf einen Blick.\n\n");
		markup.append("[accordions]");

		for (Club club : clubs) {

			// Global information
			markup.append("[accordion title=\"" + club.getName() + "\"]");
			markup.append("<ul class=\"floated-content\">");

			// Contacts
			markup.append("<li>");
			markup.append("<p class=\"caption\"><strong>Ansprechpartner</strong></p>");
			for (ClubContact c : club.getContacts()) {
				markup.append("<p>");
				appendHtml(markup, c.getFirstname(), " ");
				appendHtml(markup, c.getLastname(), "<br/>");
				appendHtml(markup, c.getStreet(), "<br/>");
				appendHtml(markup, c.getZip() + " " + c.getCity(), "<br/>");
				appendHtml(markup, c.getPhone(), "<br/>");
				appendHtml(markup, c.getMobile(), "<br/>");
				appendHtml(markup, c.getEmail());
				markup.append("</p>");
			}
			appendHtml(markup, club.getWebsite(), "<p><a target=\"_blank\" href=\"http://" + club.getWebsite() + "\">", "</a></p>");
			markup.append("</li>");

			// Outdoor venues
			markup.append("<li>");
			markup.append("<p class=\"caption\"><strong>Sportplatz</strong></p>");
			for (ClubVenue v : club.getVenues()) {
				if (VENUE_TYPE_OUTDOOR.equals(v.getType())) {
					markup.append("<p>");
					appendHtml(markup, v.getIdentifier(), "<br/>");
					appendHtml(markup, v.getStreet(), "<br/>");
					appendHtml(markup, v.getZip(), " ");
					appendHtml(markup, v.getCity());
					markup.append("</p>");
				}
			}

			// Indoor venues
			markup.append("<p class=\"caption\"><strong>Sporthalle</strong></p>");
			for (ClubVenue v : club.getVenues()) {
				if (VENUE_TYPE_INDOOR.equals(v.getType())) {
					markup.append("<p>");
					appendHtml(markup, v.getIdentifier(), "<br/>");
					appendHtml(markup, v.getStreet(), "<br/>");
					appendHtml(markup, v.getZip(), " ");
					appendHtml(markup, v.getCity());
					markup.append("</p>");
				}
			}
			markup.append("</li>");

			markup.append("</ul>");
			markup.append("<div class=\"clear-left\"></div>\n");
			markup.append("[/accordion]");
		}

		markup.append("[/accordions]\n\n");

		String clubs = "http://downloads.rtbfaustball.de/spielbetrieb/halle-2013-14/Adressen-Vereine";
		String indoor = "http://downloads.rtbfaustball.de/spielbetrieb/halle-2013-14/Adressen-Halle";
		String mngrs = "http://downloads.rtbfaustball.de/spielbetrieb/halle-2013-14/Adressen-Staffelleiter";

		markup.append("<ul>");
		markup.append("<li>Adress-Übersicht aller Faustballvereine <a href=\"" + clubs + ".pdf\">PDF</a> // <a href=\"" + clubs + ".xls\">Excel</a></li>");
		markup.append("<li>Adress-Übersicht der Sportplätze <a href=\"http://downloads.rtbfaustball.de/spielbetrieb/feld-2013/Adressen-Platz.xls\">Excel</a></li>");
		markup.append("<li>Adress-Übersicht der Sporthallen <a href=\"" + indoor + ".pdf\">PDF</a> // <a href=\"" + indoor + ".xls\">Excel</a></li>");
		markup.append("<li>Kontakt-Informationen der Staffelleiter <a href=\"" + mngrs + ".pdf\">PDF</a> // <a href=\"" + mngrs + ".xls\">Excel</a></li>");
		markup.append("</ul>\n\n");

		markup.append("[contact-form-7 id=\"21\" title=\"Änderung Vereins-Addressen\"]");

		log.info("Finished clubs conversion to HTML");

		if (persist) {
			persistHtml(escapeHtml(markup.toString()));
		}
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	protected void persistHtml(String markup) throws IOException {
		log.info("Persist HTML in " + DEFAULT_PERSISTANCE_LOCATION + "/clubs.html");
		BufferedWriter writer = null;
		try {
			writer = new BufferedWriter(new FileWriter(DEFAULT_PERSISTANCE_LOCATION + "/clubs.html"));
			writer.write(markup);
		} finally {
			if (writer != null) {
				writer.close();
			}
			log.info("Finished persisting HTML");
		}
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public void toPdf(boolean persist) throws IOException, COSVisitorException {
		log.info("Start clubs conversion to PDF");

		PDDocument document = new PDDocument();
		PDPage page = new PDPage();
		document.addPage(page);

		PDPageContentStream contentStream = new PDPageContentStream(document, page);
		int x = 60;
		int y = 730;

		// Title
		contentStream.beginText();
		contentStream.setFont(PDType1Font.HELVETICA_BOLD, 14);
		contentStream.moveTextPositionByAmount(x, y);
		contentStream.drawString("Vereine im Rheinischen Turner Bund");
		contentStream.endText();

		y = 690;
		for (Club club : clubs) {
			contentStream.beginText();
			contentStream.setFont(PDType1Font.HELVETICA_BOLD, 10);
			contentStream.moveTextPositionByAmount(x, y);
			contentStream.drawString(club.getName());
			contentStream.endText();

			// Contacts
			for (ClubContact c : club.getContacts()) {
				y -= 12;

				StringBuffer buffer = new StringBuffer();
				appendPdf(buffer, c.getFirstname());
				appendPdf(buffer, c.getLastname(), " ");
				appendPdf(buffer, c.getStreet(), ": ");
				appendPdf(buffer, c.getZip(), ", ");
				appendPdf(buffer, c.getCity(), " ");
				appendPdf(buffer, c.getPhone(), " | ");
				appendPdf(buffer, c.getMobile(), " | ");
				appendPdf(buffer, c.getEmail(), " | ");

				contentStream.beginText();
				contentStream.setFont(PDType1Font.HELVETICA, 10);
				contentStream.moveTextPositionByAmount(x + 10, y);
				contentStream.drawString(buffer.toString());
				contentStream.endText();
			}
			y -= 12;

			// Outdoor venues
			for (ClubVenue v : club.getVenues()) {
				if (VENUE_TYPE_OUTDOOR.equals(v.getType())) {
					y -= 12;

					StringBuffer buffer = new StringBuffer();
					appendPdf(buffer, "Sportplatz: ");
					appendPdf(buffer, v.getStreet());
					appendPdf(buffer, v.getZip(), ", ");
					appendPdf(buffer, v.getCity(), " ");
					appendPdf(buffer, v.getIdentifier(), " - ");

					contentStream.beginText();
					contentStream.setFont(PDType1Font.HELVETICA, 10);
					contentStream.moveTextPositionByAmount(x + 10, y);
					contentStream.drawString(buffer.toString());
					contentStream.endText();
				}
			}

			// Indoor venues
			for (ClubVenue v : club.getVenues()) {
				if (VENUE_TYPE_INDOOR.equals(v.getType())) {
					y -= 12;

					StringBuffer buffer = new StringBuffer();
					appendPdf(buffer, "Sporthalle: ");
					appendPdf(buffer, v.getStreet());
					appendPdf(buffer, v.getZip(), ", ");
					appendPdf(buffer, v.getCity(), " ");
					appendPdf(buffer, v.getIdentifier(), " - ");

					contentStream.beginText();
					contentStream.setFont(PDType1Font.HELVETICA, 10);
					contentStream.moveTextPositionByAmount(x + 10, y);
					contentStream.drawString(buffer.toString());
					contentStream.endText();
				}
			}

			y -= 24;
		}

		contentStream.close();

		// Save the results and ensure that the document is properly closed:
		if (persist) {
			log.info("Persist PDF in " + DEFAULT_PERSISTANCE_LOCATION + "/clubs.pdf");
			document.save(DEFAULT_PERSISTANCE_LOCATION + "/clubs.pdf");
			log.info("Finished persisting PDF");
		}
		document.close();

		log.info("Finished clubs conversion to PDF");
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public void toExcel() {
		log.info("Start clubs conversion to Excel");
		// TODO Auto-generated method stub
		log.info("Finished clubs conversion to Excel");
	}
}
